import { Injectable, Inject } from "@angular/core";
import { Router } from "@angular/router";
import { Actions, Effect, ofType } from "@ngrx/effects";
import { of } from "rxjs";

import { Store, select } from "@ngrx/store";
import * as fromAssets from "@/assets/store/reducers/index";
import * as fromRoot from "@/reducers/index";
import { catchError, exhaustMap, map, tap, filter } from "rxjs/operators";
import { Subscription } from "rxjs";
import { AssetsActions } from "@/assets/store/actions";
import { combineAll, debounceTime } from "rxjs/operators";

import {
  ISelectAssetsResponse,
  ISelectAssetsRequest,
  IFindAssetsRequest,
  IWithdrawRequest,
  IFindAssetsToBtcRequest
} from "@/assets/store/models/assets";

@Injectable()
export class AssetsEffects {
  constructor(
    private actions$: Actions,
    @Inject("AssetsService") private assetsService,
    @Inject("MsgService") private msgService,
    private router: Router,
    private store: Store<fromAssets.State | fromRoot.State>
  ) {}

  @Effect()
  selectAssets$ = this.actions$.pipe(
    ofType<AssetsActions.SelectAssets>(
      AssetsActions.AssetsActionTypes.SelectAssets
    ),
    map(action => action.payload.req),
    exhaustMap((req: ISelectAssetsRequest) => {
      return this.assetsService.selectAssets(req).pipe(
        map((res: any) => {
          return new AssetsActions.SelectAssetsSuccess({ res });
        }),
        catchError(error => of(new AssetsActions.SelectAssetsError({ error })))
      );
    })
  );

  @Effect({ dispatch: false })
  selectAssetsSuccess$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.SelectAssetsSuccess),
    tap((response: any) => {
      const { payload } = response;
      // if (200 === payload.res.code) {
      //   this.msgService.success("success");
      // } else {
      //   this.msgService.error("error");
      // }
    })
  );

  @Effect({ dispatch: false })
  selectAssetsError$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.SelectAssetsError),
    tap(() => {
      this.msgService.error("error");
    })
  );

  // here is repeat with select assets ,please remove it after
  @Effect()
  selectCoinConfig$ = this.actions$.pipe(
    ofType<AssetsActions.SelectCoinConfig>(
      AssetsActions.AssetsActionTypes.SelectCoinConfig
    ),
    map(action => action.payload),
    exhaustMap(payload => {
      return this.assetsService.selectCoinConfig(payload.req).pipe(
        map((res: any) => {
          return new AssetsActions.SelectCoinConfigSuccess({ res });
        }),
        catchError(error =>
          of(new AssetsActions.SelectCoinConfigError({ error }))
        )
      );
    })
  );

  @Effect({ dispatch: false })
  selectCoinConfigSuccess$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.SelectCoinConfigSuccess),
    tap((response: any) => {
      const { payload } = response;
      if (200 === payload.res.code) {
        // this.msgService.success("success");
      } else {
        this.msgService.error("error");
      }
    })
  );

  @Effect({ dispatch: false })
  selectCoinConfigError$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.SelectCoinConfigError),
    tap(() => {
      this.msgService.error("error");
    })
  );

  @Effect()
  findAssets$ = this.actions$.pipe(
    ofType<AssetsActions.FindAssets>(
      AssetsActions.AssetsActionTypes.FindAssets
    ),
    map(action => action.payload.req),
    exhaustMap((req: IFindAssetsRequest) => {
      return this.assetsService.findAssets(req).pipe(
        map((res: any) => {
          return new AssetsActions.FindAssetsSuccess({ res });
        }),
        catchError(error => of(new AssetsActions.FindAssetsError({ error })))
      );
    })
  );

  @Effect({ dispatch: false })
  findAssetsSuccess$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.FindAssetsSuccess),
    tap((response: any) => {
      const { payload } = response;
      // if (200 === payload.res.code) {
      //   this.msgService.success("success");
      // } else {
      //   this.msgService.error("error");
      // }
    })
  );

  @Effect({ dispatch: false })
  findAssetsError$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.FindAssetsError),
    tap(() => {
      this.msgService.error("error");
    })
  );

  @Effect()
  findAssetsToBtc$ = this.actions$.pipe(
    ofType<AssetsActions.FindAssetsToBtc>(
      AssetsActions.AssetsActionTypes.FindAssetsToBtc
    ),
    map(action => action.payload.req),
    exhaustMap((req: IFindAssetsToBtcRequest) => {
      return this.assetsService.findAssetsToBtc(req).pipe(
        map((res: any) => {
          return new AssetsActions.FindAssetsToBtcSuccess({ res });
        }),
        catchError(error =>
          of(new AssetsActions.FindAssetsToBtcError({ error }))
        )
      );
    })
  );

  @Effect({ dispatch: false })
  findAssetsToBtcSuccess$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.FindAssetsToBtcSuccess),
    tap((response: any) => {
      const { payload } = response;
      // if (200 === payload.res.code) {
      //   this.msgService.success("success");
      // } else {
      //   this.msgService.error("error");
      // }
    })
  );

  @Effect({ dispatch: false })
  findAssetsToBtcError$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.FindAssetsToBtcError),
    tap(() => {
      this.msgService.error("error");
    })
  );

  @Effect()
  withdraw$ = this.actions$.pipe(
    ofType<AssetsActions.Withdraw>(AssetsActions.AssetsActionTypes.Withdraw),
    map(action => action.payload),
    exhaustMap(payload => {
      return this.assetsService.withdraw(payload.req).pipe(
        map((res: any) => {
          return new AssetsActions.WithdrawSuccess({ res, cpt: payload.cpt });
        }),
        catchError(error => of(new AssetsActions.WithdrawError({ error })))
      );
    })
  );

  @Effect({ dispatch: false })
  withdrawSuccess$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.WithdrawSuccess),
    tap((response: any) => {
      const { payload } = response;
      if (200 === payload.res.code) {
        this.msgService.success("success");
        // payload.cpt.validateForm.reset();
        payload.cpt.validateForm.controls.address.reset();
        payload.cpt.validateForm.controls.amount.reset();
        payload.cpt.validateForm.controls.payPwd.reset();
        // this.router.navigate(["assets/history"]);
        this.store.dispatch(
          new AssetsActions.SelectWithdrawHistory({
            req: {
              ...payload.cpt.req
            },
            cpt: payload.cpt
          })
        );
      } else {
        this.msgService.error("error");
      }
    })
  );

  @Effect({ dispatch: false })
  withdrawError$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.WithdrawError),
    tap(() => {
      this.msgService.error("error");
    })
  );

  @Effect()
  selectDepositHistory$ = this.actions$.pipe(
    ofType<AssetsActions.SelectDepositHistory>(
      AssetsActions.AssetsActionTypes.SelectDepositHistory
    ),
    map(action => action.payload),
    exhaustMap(payload => {
      return this.assetsService.selectDepositHistory(payload.req).pipe(
        map((res: any) => {
          return new AssetsActions.SelectDepositHistorySuccess({
            res,
            cpt: payload.cpt
          });
        }),
        catchError(error =>
          of(new AssetsActions.SelectDepositHistoryError({ error }))
        )
      );
    })
  );

  @Effect({ dispatch: false })
  selectDepositHistorySuccess$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.SelectDepositHistorySuccess),
    tap((response: any) => {
      const { payload } = response;
      if (200 === payload.res.code) {
        // this.msgService.success("success");
      } else {
        // this.msgService.error("error");
      }
    })
  );

  @Effect({ dispatch: false })
  selectDepositHistoryError$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.SelectDepositHistoryError),
    tap(() => {
      // this.msgService.error("error");
    })
  );

  @Effect()
  selectWithdrawHistory$ = this.actions$.pipe(
    ofType<AssetsActions.SelectWithdrawHistory>(
      AssetsActions.AssetsActionTypes.SelectWithdrawHistory
    ),
    map(action => action.payload),
    exhaustMap(payload => {
      return this.assetsService.selectWithdrawHistory(payload.req).pipe(
        map((res: any) => {
          return new AssetsActions.SelectWithdrawHistorySuccess({
            res,
            cpt: payload.cpt
          });
        }),
        catchError(error =>
          of(new AssetsActions.SelectWithdrawHistoryError({ error }))
        )
      );
    })
  );

  @Effect({ dispatch: false })
  selectWithdrawHistorySuccess$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.SelectWithdrawHistorySuccess),
    tap((response: any) => {
      const { payload } = response;
      if (200 === payload.res.code) {
        // this.msgService.success("success");
      } else {
        // this.msgService.error("error");
      }
    })
  );

  @Effect({ dispatch: false })
  selectWithdrawHistoryError$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.SelectWithdrawHistoryError),
    tap(() => {
      // this.msgService.error("error");
    })
  );

  @Effect()
  addAddress$ = this.actions$.pipe(
    ofType<AssetsActions.AddAddress>(
      AssetsActions.AssetsActionTypes.AddAddress
    ),
    map(action => action.payload),
    exhaustMap(payload => {
      return this.assetsService.addAddress(payload.req).pipe(
        map((res: any) => {
          return new AssetsActions.AddAddressSuccess({
            res,
            cpt: payload.cpt
          });
        }),
        catchError(error => of(new AssetsActions.AddAddressError({ error })))
      );
    })
  );

  @Effect({ dispatch: false })
  addAddressSuccess$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.AddAddressSuccess),
    tap((response: any) => {
      const { payload } = response;
      if (200 === payload.res.code) {
        this.msgService.success("success");
        payload.cpt.initWithdrawAddressLists();
      } else {
        this.msgService.error("error");
      }
    })
  );

  @Effect({ dispatch: false })
  addAddressError$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.AddAddressError),
    tap(() => {
      this.msgService.error("error");
    })
  );

  @Effect()
  delAddress$ = this.actions$.pipe(
    ofType<AssetsActions.DelAddress>(
      AssetsActions.AssetsActionTypes.DelAddress
    ),
    map(action => action.payload),
    exhaustMap(payload => {
      return this.assetsService.delAddress(payload.req).pipe(
        map((res: any) => {
          return new AssetsActions.DelAddressSuccess({
            res,
            cpt: payload.cpt
          });
        }),
        catchError(error => of(new AssetsActions.DelAddressError({ error })))
      );
    })
  );

  @Effect({ dispatch: false })
  delAddressSuccess$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.DelAddressSuccess),
    tap((response: any) => {
      const { payload } = response;
      if (200 === payload.res.code) {
        this.msgService.success("success");
        payload.cpt.initWithdrawAddressLists();
      } else {
        this.msgService.error("error");
      }
    })
  );

  @Effect({ dispatch: false })
  delAddressError$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.DelAddressError),
    tap(() => {
      this.msgService.error("error");
    })
  );

  @Effect()
  selectWithdrawAddress$ = this.actions$.pipe(
    ofType<AssetsActions.DelAddress>(
      AssetsActions.AssetsActionTypes.SelectWithdrawAddress
    ),
    map(action => action.payload),
    exhaustMap(payload => {
      return this.assetsService.selectWithdrawAddress(payload.req).pipe(
        map((res: any) => {
          return new AssetsActions.SelectWithdrawAddressSuccess({
            res,
            cpt: payload.cpt
          });
        }),
        catchError(error =>
          of(new AssetsActions.SelectWithdrawAddressError({ error }))
        )
      );
    })
  );

  @Effect({ dispatch: false })
  selectWithdrawAddressSuccess$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.SelectWithdrawAddressSuccess),
    tap((response: any) => {
      const { payload } = response;
      if (200 === payload.res.code) {
        // this.msgService.success("success");
      } else {
        // this.msgService.error("error");
      }
    })
  );

  @Effect({ dispatch: false })
  selectWithdrawAddressError$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.SelectWithdrawAddressError),
    tap(() => {
      this.msgService.error("error");
    })
  );

  @Effect()
  findDepositAddress$ = this.actions$.pipe(
    ofType<AssetsActions.DelAddress>(
      AssetsActions.AssetsActionTypes.FindDepositAddress
    ),
    map(action => action.payload),
    exhaustMap(payload => {
      return this.assetsService.findDepositAddress(payload.req).pipe(
        map((res: any) => {
          return new AssetsActions.FindDepositAddressSuccess({
            res,
            cpt: payload.cpt
          });
        }),
        catchError(error =>
          of(new AssetsActions.FindDepositAddressError({ error }))
        )
      );
    })
  );

  @Effect({ dispatch: false })
  findDepositAddressSuccess$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.FindDepositAddressSuccess),
    tap((response: any) => {
      const { payload } = response;
      if (200 === payload.res.code) {
        // this.msgService.success("success");
      } else {
        // this.msgService.error("error");
      }
    })
  );

  @Effect({ dispatch: false })
  findDepositAddressError$ = this.actions$.pipe(
    ofType(AssetsActions.AssetsActionTypes.FindDepositAddressError),
    tap(() => {
      this.msgService.error("error");
    })
  );
}
